package io.github.protocol.gitlab.client

import io.circe.Decoder
import io.circe.generic.semiauto.deriveDecoder
import io.circe.parser.decode
import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.http.scaladsl.Http
import org.apache.pekko.http.scaladsl.model.{HttpHeader, HttpMethods, HttpRequest}
import org.apache.pekko.stream.Materializer

import scala.concurrent.duration.DurationInt
import scala.concurrent.{ExecutionContext, Future}

case class Project(id: Int, name: String, description: Option[String])

object Project {
  implicit val decoder: Decoder[Project] = deriveDecoder[Project]
}

case class Configuration(host: String, port: Int, token: String)

class GitlabClient(val configuration: Configuration)(implicit system: ActorSystem,
                                                     materializer: Materializer,
                                                     ec: ExecutionContext,
) {
  private val baseUrl = s"${configuration.host}:${configuration.port}/api/v4"
  private val authHeaderValue = s"Bearer ${configuration.token}"

  def listProjects(): Future[Seq[Project]] = {
    val request = HttpRequest(
      method = HttpMethods.GET,
      uri = s"$baseUrl/projects",
      headers = List(HttpHeader.parse("Authorization", authHeaderValue) match {
        case HttpHeader.ParsingResult.Ok(header, _) => header
        case HttpHeader.ParsingResult.Error(error) => throw new RuntimeException(s"Failed to parse header: $error")
      })
    )

    for {
      response <- Http().singleRequest(request)
      entity <- response.entity.toStrict(5.seconds)
      jsonResponse = entity.data.utf8String
      projects <- decode[Seq[Project]](jsonResponse) match {
        case Right(projects) => Future.successful(projects)
        case Left(error)     => Future.failed(new RuntimeException(s"Failed to decode JSON: $error"))
      }
    } yield projects
  }
}
